package com.yang.framework.disruptor;


import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.YieldingWaitStrategy;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 类的功能描述
 *
 * @author 杨 强
 * @package com.yang.framework.disruptor
 * @createTime 2023-09-10 14:47
 */
@Configuration
public class RingBufferManager {

    @Bean("payNoticeRingBuffer")
    public RingBuffer<PayNoticeEvent> payNoticeEventRingBuffer(){
        // 创建线程池
        ExecutorService executor = Executors.newSingleThreadExecutor();

        // 缓冲池大小
        int bufferSize = 2 * 1024;

        // 创建工厂
        PayNoticeEventFactory factory = new PayNoticeEventFactory();

        // 创建 Disruptor 示例
        // 1第一个参数为工厂付象，用于创建一个个的PayNoticeEvent,PayNoticeEvent是实际的消费数据
        // 2第二个参数为缓冲区大小
        // 3第三个参数线程池,进行Disruptor内部的数据接收处理调度
        // 4第四个参数ProducerType, SINGLE为单个生产者, MULTI为多个生产者
        // TODO 杨强 我们有多个支付渠道的通知,那么生产者就是多个;
        // 5第五个采纳数WaitStrategy: 生产者者消费者的策略, 对于生产者和消费者处理速度不一样的情况的策略处理:
        Disruptor<PayNoticeEvent> disruptor = new Disruptor<>(factory, bufferSize, executor, ProducerType.SINGLE, new YieldingWaitStrategy());


        // 连接消费者, 消费者可以创建多个
        disruptor.handleEventsWith(new PayNoticeEventHandler());

        // 启动disruptor线程
        // TODO 杨强 disruptor start之后，有什么好的方法去保证这个disruptor是一直活着的，可用的？
        disruptor.start();

        // 获取存放数据的具体容器, 用来发布事件消息
        RingBuffer<PayNoticeEvent> ringBuffer = disruptor.getRingBuffer();

        return ringBuffer;
    }

}
